home *** CD-ROM | disk | FTP | other *** search
/ Aminet 41 / Aminet 41 (2001)(Schatztruhe)[!][Feb 2001].iso / Aminet / dev / c / libiconv_src.lha / src / gentranslit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-11-07  |  5.8 KB  |  218 lines

  1. /*
  2.  * Generates a table of small strings, used for transliteration, from a table
  3.  * containing lines of the form
  4.  *   Unicode <tab> iso-8859-1 replacement <tab> # comment
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <stdbool.h>
  10.  
  11. int main (int argc, char *argv[])
  12. {
  13.   unsigned char data[0x100000];
  14.   int uni2index[0x10000];
  15.   int index;
  16.  
  17.   if (argc != 1)
  18.     exit(1);
  19.  
  20.   printf("\n");
  21.   printf("/*\n");
  22.   printf(" * Transliteration table\n");
  23.   printf(" */\n");
  24.   printf("\n");
  25.   {
  26.     int c;
  27.     int j;
  28.     for (j = 0; j < 0x10000; j++)
  29.       uni2index[j] = -1;
  30.     index = 0;
  31.     for (;;) {
  32.       c = getc(stdin);
  33.       if (c == EOF)
  34.         break;
  35.       if (c == '#') {
  36.         do { c = getc(stdin); } while (!(c == EOF || c == '\n'));
  37.         continue;
  38.       }
  39.       ungetc(c,stdin);
  40.       if (scanf("%x",&j) != 1)
  41.         exit(1);
  42.       c = getc(stdin);
  43.       if (c != '\t')
  44.         exit(1);
  45.       for (;;) {
  46.         c = getc(stdin);
  47.         if (c == EOF || c == '\n')
  48.           exit(1);
  49.         if (c == '\t')
  50.           break;
  51.         if (uni2index[j] < 0) {
  52.           uni2index[j] = index;
  53.           data[index++] = 0;
  54.         }
  55.         if (c >= 0x80) {
  56.           /* Finish reading an UTF-8 character. */
  57.           if (c < 0xc0)
  58.             exit(1);
  59.           else {
  60.             unsigned int i = (c < 0xe0 ? 2 : c < 0xf0 ? 3 : c < 0xf8 ? 4 : c < 0xfc ? 5 : 6);
  61.             c &= (1 << (8-i)) - 1;
  62.             while (--i > 0) {
  63.               int cc = getc(stdin);
  64.               if (!(cc >= 0x80 && cc < 0xc0))
  65.                 exit(1);
  66.               c <<= 6; c |= (cc & 0x3f);
  67.             }
  68.           }
  69.         }
  70.         data[index++] = (unsigned char) c;
  71.       }
  72.       data[uni2index[j]] = index - uni2index[j] - 1;
  73.       do { c = getc(stdin); } while (!(c == EOF || c == '\n'));
  74.     }
  75.   }
  76.   printf("static const unsigned char translit_data[%d] = {",index);
  77.   {
  78.     int i;
  79.     for (i = 0; i < index; i++) {
  80.       if (data[i] < 32)
  81.         printf("\n %3d,",data[i]);
  82.       else if (data[i] == '\'')
  83.         printf("'\\'',");
  84.       else if (data[i] < 127)
  85.         printf(" '%c',",data[i]);
  86.       else
  87.         printf("0x%02X,",data[i]);
  88.     }
  89.     printf("\n};\n");
  90.   }
  91.   printf("\n");
  92.   {
  93.     bool pages[0x100];
  94.     int line[0x2000];
  95.     int tableno;
  96.     struct { int minline; int maxline; int usecount; const char* suffix; } tables[0x2000];
  97.     int i, j, p, j1, j2, t;
  98.  
  99.     for (p = 0; p < 0x100; p++)
  100.       pages[p] = false;
  101.     for (j = 0; j < 0x10000; j++)
  102.       if (uni2index[j] >= 0)
  103.         pages[j>>8] = true;
  104.     for (j1 = 0; j1 < 0x2000; j1++) {
  105.       bool all_invalid = true;
  106.       for (j2 = 0; j2 < 8; j2++) {
  107.         j = 8*j1+j2;
  108.         if (uni2index[j] >= 0)
  109.           all_invalid = false;
  110.       }
  111.       if (all_invalid)
  112.         line[j1] = -1;
  113.       else
  114.         line[j1] = 0;
  115.     }
  116.     tableno = 0;
  117.     for (j1 = 0; j1 < 0x2000; j1++) {
  118.       if (line[j1] >= 0) {
  119.         if (tableno > 0
  120.             && ((j1 > 0 && line[j1-1] == tableno-1)
  121.                 || ((tables[tableno-1].maxline >> 5) == (j1 >> 5)
  122.                     && j1 - tables[tableno-1].maxline <= 8))) {
  123.           line[j1] = tableno-1;
  124.           tables[tableno-1].maxline = j1;
  125.         } else {
  126.           tableno++;
  127.           line[j1] = tableno-1;
  128.           tables[tableno-1].minline = tables[tableno-1].maxline = j1;
  129.         }
  130.       }
  131.     }
  132.     for (t = 0; t < tableno; t++) {
  133.       tables[t].usecount = 0;
  134.       j1 = 8*tables[t].minline;
  135.       j2 = 8*(tables[t].maxline+1);
  136.       for (j = j1; j < j2; j++)
  137.         if (uni2index[j] >= 0)
  138.           tables[t].usecount++;
  139.     }
  140.     for (t = 0, p = -1, i = 0; t < tableno; t++) {
  141.       if (tables[t].usecount > 1) {
  142.         char* s;
  143.         if (p == tables[t].minline >> 5) {
  144.           s = (char*) malloc(5+1);
  145.           sprintf(s, "%02x_%d", p, ++i);
  146.         } else {
  147.           p = tables[t].minline >> 5;
  148.           s = (char*) malloc(2+1);
  149.           sprintf(s, "%02x", p);
  150.         }
  151.         tables[t].suffix = s;
  152.       } else
  153.         tables[t].suffix = NULL;
  154.     }
  155.     {
  156.       p = -1;
  157.       for (t = 0; t < tableno; t++)
  158.         if (tables[t].usecount > 1) {
  159.           p = 0;
  160.           printf("static const short translit_page%s[%d] = {\n", tables[t].suffix, 8*(tables[t].maxline-tables[t].minline+1));
  161.           for (j1 = tables[t].minline; j1 <= tables[t].maxline; j1++) {
  162.             if ((j1 % 0x20) == 0 && j1 > tables[t].minline)
  163.               printf("  /* 0x%04x */\n", 8*j1);
  164.             printf(" ");
  165.             for (j2 = 0; j2 < 8; j2++) {
  166.               j = 8*j1+j2;
  167.               printf(" %3d,", uni2index[j]);
  168.             }
  169.             printf(" /* 0x%02x-0x%02x */\n", 8*(j1 % 0x20), 8*(j1 % 0x20)+7);
  170.           }
  171.           printf("};\n");
  172.         }
  173.       if (p >= 0)
  174.         printf("\n");
  175.     }
  176.     printf("#define translit_index(wc) \\\n  (");
  177.     for (j1 = 0; j1 < 0x2000;) {
  178.       t = line[j1];
  179.       for (j2 = j1; j2 < 0x2000 && line[j2] == t; j2++);
  180.       if (t >= 0) {
  181.         if (j1 != tables[t].minline) abort();
  182.         if (j2 > tables[t].maxline+1) abort();
  183.         j2 = tables[t].maxline+1;
  184.       }
  185.       if (t == -1) {
  186.       } else {
  187.         if (t >= 0 && tables[t].usecount == 0) abort();
  188.         if (t >= 0 && tables[t].usecount == 1) {
  189.           if (j2 != j1+1) abort();
  190.           for (j = 8*j1; j < 8*j2; j++)
  191.             if (uni2index[j] >= 0) {
  192.               printf("wc == 0x%04x ? %d", j, uni2index[j]);
  193.               break;
  194.             }
  195.         } else {
  196.           if (j1 == 0) {
  197.             printf("wc < 0x%04x", 8*j2);
  198.           } else {
  199.             printf("wc >= 0x%04x && wc < 0x%04x", 8*j1, 8*j2);
  200.           }
  201.           printf(" ? translit_page%s[wc", tables[t].suffix);
  202.           if (tables[t].minline > 0)
  203.             printf("-0x%04x", 8*j1);
  204.           printf("]");
  205.         }
  206.         printf(" : \\\n   ");
  207.       }
  208.       j1 = j2;
  209.     }
  210.     printf("-1)\n");
  211.   }
  212.  
  213.   fflush(stdout);
  214.   if (ferror(stdout))
  215.     exit(1);
  216.   exit(0);
  217. }
  218.